#
#   Game.py
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; version 2 of the License.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   Copyright
#   Author: Nicholas F. Hoover
#   Contributors: Salvatore S. Gionfriddo
#   Created: 2007.07.03
#   Last Modified: 2007.11.05
#

import pygame
import Messages, Spawner, EventHandler, GameObject, Settings
from Options import Options
from hud import Background, HUD
from hkm import HotKeyMenu, HotKeyMenuSystem
from GameObjectManager import GameObjectManager
from Level import Level
from Levels import Levels
from Statistics import Statistics

class Game(object):

    POINTS_PER_BASICKID = 500
    POINTS_PER_FASTKID = 600
    POINTS_PER_STRONGKID = 700
    POINTS_PER_FATKID = 500
    POINTS_PER_WEAKKID = 50
    POINTS_PER_THROWINGKID = 750
    POINTS_PER_SANTAKID = 650
    POINTS_PER_ELFKID = 600
    POINTS_PER_DEVILKID = 600
    
    POINTS_PER_FINK = 4000
    POINTS_PER_MEGAKID = 4000
    POINTS_PER_RINGKID = 4000

    POINTS_PER_POWERUP = -1000
    
    POINTS_PER_TICK = 1

    FPS = 30
    
    def __init__(self, screen, rManager, mission):
        self.screen = screen
        self.background = Background(self.screen, (0,0), self.screen.get_size())

        GameObject.RESOURCE_MANAGER = rManager #set the 'static' variable
        self.gameObjectManager = GameObjectManager(screen, rManager)
                
        self.clock = pygame.time.Clock()
        self.eventHandler = EventHandler.GameEventHandler(self)
        
        #HUD & HKM
        self.hud = HUD(self.screen)
        
        self.hkms = HotKeyMenuSystem(self.screen, (10,50), view_inventory=self.gameObjectManager.hero.viewItemCount, use_inventory=self.gameObjectManager.hero.useItem)
        
        self.musicOn = False
        
        self.statTrackers = Settings.getStatTrackers(self.gameObjectManager, Statistics, self.getCurrentLevel)
        self.gameObjectManager.addSpawners()
        self.spawnFunctions = {}
        for enemy in Settings.ENEMIES:
            self.spawnFunctions.update({enemy: self.gameObjectManager.__dict__['add'+enemy]})
            self.spawnFunctions.update({'Para'+enemy: self.gameObjectManager.__dict__['addPara'+enemy]})
            self.spawnFunctions.update({'Hole'+enemy: self.gameObjectManager.__dict__['addHole'+enemy]})
        for powerup in Settings.POWERUPS:
            self.spawnFunctions.update({powerup: self.gameObjectManager.__dict__['add'+powerup]})
        self.levelManager = Levels(self.statTrackers, self.spawnFunctions)
        self.mission = mission
        self.initLevels()
        self.reset()
        
    def setMission(self, mission):
        self.mission = mission
        self.initLevels()
        self.reset()

    #def cancel(self):
    #    self.hkms.cancel()
    #    self.hkms_on = False
        
    def getCurrentLevel(self):
        return self.currentLevel
    
    def initLevels(self):
        self.levelManager.loadLevels(self.mission)
        self.levels = self.levelManager.getLevels()
        for i in range(1,len(self.levels)):
            self.gameObjectManager.egStats.addLevel()

        
    def nextLevel(self):
        if self.currentLevel + 1 < len(self.levels):
            self.currentLevel += 1
            self.gameObjectManager.setSpawners(self.levels[self.currentLevel].spawners)
            self.gameObjectManager.level += 1
            self.tintScreen()
            Messages.printLevel(self.screen, self.levels[self.currentLevel].name, self.levels[self.currentLevel].description)
            self.background.setColor(self.levels[self.currentLevel].background)
            self.pauseIt(doTint = False)
        else:
            #Messages.printWin()
            #self.pauseIt()
            self.win = True
            self.quitGame()

    def isLevelComplete(self):
        return self.levels[self.currentLevel].isLevelComplete()
            
    def mainLoop(self):

        self.nextLevel()
        hkms_was_on = None
        while self.gameObjectManager.hero.isAlive() and not self.quit:
            if self.pause:
                self.pauseIt()
            self.clock.tick(self.FPS)
            self.eventHandler.doEvents(pygame.event.get())
            self.background.draw()
            self.gameObjectManager.update()
            
            dirty_rects = self.gameObjectManager.draw()
            
            if self.isLevelComplete():
                self.nextLevel()
            
            (health, hunger, heartBurn, gas, speed, regen, toughness)  = self.gameObjectManager.hero.getStats()
            totalKills = self.statTrackers["TotalKills"]()
            kills = self.statTrackers["Kills"]()
            self.hud.update(totalKills, kills, health, hunger, heartBurn, gas, speed, regen, toughness, self.levels[self.currentLevel].getGoalStatus(), self.clock.get_fps())
            dirty_rects += self.hud.draw()
            
            if self.hkms.on:
                hkms_was_on = self.hkms.draw()
                dirty_rects += hkms_was_on
            elif hkms_was_on:
                dirty_rects += hkms_was_on
                hkms_was_on = None
                
            dirty_rects += [(0,0,800,80), (0,540,800,60)]
            #print dirty_rects
            pygame.display.update(dirty_rects)

        if not self.gameObjectManager.hero.isAlive():
            #Do death sequence
            #This is a little bit #HACK
            self.background.draw()
            self.gameObjectManager.killEG(self.screen)
            self.hud.draw()
        elif self.quit:
            pass
    
    def reset(self):
        self.hud.reset()
        self.gameObjectManager.reset()
        self.done = False
        self.pause = False
        self.currentLevel = -1 # so can call next level to get to 0
        for level in self.levels:
            level.reset()
        self.quit = False
        self.win = False
        
    def pauseIt(self, doQuit = False, doTint = True):
        self.hud.draw()
        if doTint:
            self.tintScreen()
        if doQuit:
            Messages.printQuit(self.screen)
        else:
            Messages.printPaused(self.screen)
        pygame.display.flip()
        if Options.SOUND['MUSIC_ON']:
            pygame.mixer.music.set_volume(pygame.mixer.music.get_volume()/2.0)
            
        EventHandler.waitForKeyOrQuit(Options.CONTROLS['ENTER'], self.quitGame)
        self.pause = False
        self.gameObjectManager.hero.clearNextAction()
            
        if Options.SOUND['MUSIC_ON']:
            pygame.mixer.music.set_volume(pygame.mixer.music.get_volume()*2.0)
        
        self.background.draw()
        pygame.display.flip()
            
    def getScore(self):
        score = []

        #KIDS
        for enemy in Settings.ENEMIES:
            score += [(Game.__dict__['POINTS_PER_'+enemy.upper()], self.statTrackers['Total'+enemy+'Kills'](), Settings.ENEMIES[enemy][0])]
        
        #TIME
        score += [(Game.POINTS_PER_TICK, self.gameObjectManager.egStats.view([Statistics.TIME]), "Time Score")]
        
        #POWERUPS
        score += [(Game.POINTS_PER_POWERUP, self.gameObjectManager.egStats.view([Statistics.EATEN, Statistics.POWERUP]), "Power Up Penalty")]
        
        return score


    def toggleMusic(self):
        if Options.SOUND['MUSIC_ON']:
            pygame.mixer.music.pause()
        else:
            pygame.mixer.music.unpause()
        Options.SOUND['MUSIC_ON'] = not Options.SOUND['MUSIC_ON']



    def startMusic(self):
        self.musicOn = True
        pygame.mixer.music.play(-1)

    def tintScreen(self):
        tint = pygame.Surface(self.screen.get_size())
        tint.fill((0,0,0))
        tint.set_alpha(40)
        self.screen.blit(tint,(0,0))


    def quitGame(self):
        self.quit = True

